using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace Sapphire.Linq.Framework
{
    public static class SPExtensions
    {
        public static IEnumerable<T> Include<T>(this IEnumerable<T> items, params T[] addins)
        {
            foreach (var item in items)
            {
                yield return item;
            }

            foreach (var addin in addins)
            {
                yield return addin;
            }
        }

        public static string ToStringSafe(this object target)
        {
            return target == null ? string.Empty : target.ToString();
        }

        public static SPList GetListByUrl(this SPWeb web, string listUrl)
        {
            var webUrl = web.ServerRelativeUrl;

            if (listUrl.Contains(webUrl))
                return web.GetList(listUrl);

            var webRelativeListUrl = SPUrlUtility.CombineUrl(webUrl, listUrl);

            return web.GetList(SPEncode.UrlEncodeAsUrl(webRelativeListUrl));
        }

        public static Expression<Func<T, bool>> GetByIds<T>(this IEnumerable<SPFieldLookupValue> fieldLookupValueCollection)
        {
            var pe = Expression.Parameter(typeof(T), "s");
            var property = Expression.Property(pe, "ID");

            var ors = fieldLookupValueCollection
                .Select(v => Expression.Equal(property, Expression.Constant(v.LookupId)))
                .Cast<Expression>()
                .Aggregate(GenerateOr);

            return Expression.Lambda<Func<T, bool>>(ors, pe);
        }

        private static Expression GenerateOr(Expression arg1, Expression arg2)
        {
            arg1 = arg1 is LambdaExpression ? (arg1 as LambdaExpression).Body : arg1;
            arg2 = arg2 is LambdaExpression ? (arg2 as LambdaExpression).Body : arg2;

            return Expression.Or(arg1, arg2);
        }
    }
}